package com.xnx3.wangmarket;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import com.xnx3.ClassUtil;
import com.xnx3.net.AuthHttpUtil;
import com.xnx3.net.HttpResponse;
import net.sf.json.JSONObject;

/**
 * 
 * 提前进行设置：
 * Authorization.domain = xxxx;
 * Authorization.auth_id = xxxx;
 * Authorization.version = xxxx;
 * Authorization.softType = xxx;
 * 设置完后：
 * new Authorization(); 即可启动鉴权
 * @author 管雷鸣
 *
 */
public class Authorization {
	public static Boolean copyright = false;	//是否显示版权信息。true显示网市场版权信息 
	public static String auth_id;	//授权码
	private static String domain;	//泛解析的二级域名
	private static int version;		//当前系统的版本号，格式如 4001000
	public static Map<String, String> authAppendParams; //授权追加的参数。针对不同的应用，可能授权的某些参数也会不一样，所以额外单独增加的这个。如果不为null且有数值，这个参数则会生效，加入授权请求
	
	/*
	 * 当前系统类型，
	 * 1:网市场云建站(默认)  
	 * 2:网市场云商城
	 * 3:网市场云建站无服务器版本
	 * 4:网市场云建站 seo 版本
	 * 5:tcdn
	 * 6:translate.service
	 */
	private static int softType = 1;	
	
	private static int sleeptime = 1000 * 60 * 30;	//延迟等待的时间，单位毫秒 ，默认是30分钟
	
	private static int gainNumber = 0;	//获取次数，也就是从云端请求授权信息的次数
	
	private static Thread thread;	//授权检测线程。每间隔1小时检测一次
	/**
	 * 设置当前网市场系统的泛解析主域名
	 * @param setDomain
	 */
	public static void setDomain(String setDomain){
		if(setDomain == null || setDomain.equals("")){
			Authorization.domain = "null";
		}else{
			Authorization.domain = setDomain;
		}
	}
	/**
	 * 设置当前网市场系统的版本号
	 * @param version 格式如 4009000
	 */
	public static void setVersion(Integer version){
		if(version == null){
			Authorization.version = 0;
			return;
		}
		Authorization.version = version;
	}
	
	public static void setSoftType(int softType) {
		Authorization.softType = softType;
	}
	/**
	 * 执行授权验证。 只需要调用一次即可。当然调用多次也无效。
	 * 需要提前设置好 domain、version 、 softType
	 */
	public static void auth(){
		if(thread == null){
			if(auth_id == null || auth_id.length() == 0) {
				//会先从wangMarketConfig.xml中取，如果没有配置，再从  application.properties 中取
				if(ClassUtil.classExist("org.apache.commons.configuration.FileConfiguration")) {
					try {
						Class<?> cla = Class.forName("com.xnx3.ConfigManagerUtil");
						Object invoke = null;
						try {
							invoke = cla.newInstance();
							//运用newInstance()来生成这个新获取方法的实例  
							Method m = cla.getMethod("getSingleton",new Class[]{String.class});
							//动态构造的Method对象invoke委托动态构造的InvokeTest对象，执行对应形参的add方法
							Object o = m.invoke(invoke, new Object[]{"wangMarketConfig.xml"});
							if(o != null && !o.equals("null")){
								Method vmt = cla.getMethod("getValue",new Class[]{String.class});
								Object resultObj = vmt.invoke(invoke, new Object[]{"authorize"});
								if(resultObj != null && !resultObj.equals("null")){
									auth_id = resultObj.toString();
								}
							}
						} catch (Exception e) {
							//e.printStackTrace();
						}
					} catch (ClassNotFoundException e) {
						//e.printStackTrace();
					} 
				}
				
				
				
				if(auth_id == null || auth_id.equals("")){
					//再去读application.properties配置文件中的授权码
					String className = "com.xnx3.j2ee.util.ApplicationPropertiesUtil";
					if(ClassUtil.classExist("org.apache.commons.configuration.FileConfiguration")) {
						try {
							Class<?> cla = Class.forName(className);
							Object invoke = null;
							try {
								invoke = cla.newInstance();
								//运用newInstance()来生成这个新获取方法的实例  
								Method m = cla.getMethod("getProperty",new Class[]{String.class});
								//动态构造的Method对象invoke委托动态构造的InvokeTest对象，执行对应形参的add方法
								Object o = m.invoke(invoke, new Object[]{"authorize"});
								if(o != null && !o.equals("null")){
									auth_id = o.toString();
								}
							} catch (Exception e) {
								e.printStackTrace();
							}
						} catch (ClassNotFoundException e) {
							e.printStackTrace();
						}
					}
				}
				if(auth_id != null && auth_id.trim().length() == 64){
					//是64位授权码，可以判断是否是真的授权，每间隔半小时进行一次
					sleeptime = 1000 * 60 * 30;
				}else{
					//授权码都没有，肯定未授权用户
					sleeptime = 1000 * 60 * 60 * 24;	//一天请求一次
				}
			}
			
			//创建授权线程
			thread = new Thread(new Runnable() {
				public void run() {
					
					while(true){
						//给1min延迟时间，给启动项目时间
						try {
							Thread.sleep(6*1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						
						String cpuid = "";
						try {
							cpuid = getCpuId();
						} catch (Exception e1) {
							//e1.printStackTrace();
						}
						
						AuthHttpUtil http = new AuthHttpUtil();
						Map<String, String> params = new HashMap<String, String>();
						if(authAppendParams != null && authAppendParams.size() > 0) {
							params.putAll(authAppendParams);
						}
						params.put("auth", auth_id);
						params.put("domain", domain);
						params.put("softType", softType+"");
						params.put("version", Authorization.version+"");
						
						String requestUrl = "http://cloud.wscso.com/auth?auth="+auth_id+"&version="+Authorization.version+"&softType="+softType+"&domain="+domain+"&machineCode="+cpuid;

						HttpResponse hr = null;
						try {
							hr = http.post(requestUrl, params);
						} catch (Exception e) {
							System.out.println("authorization service exception, but does not affect the system, you can still feel free to use !");
							//如果异常，那估计就是联网不大行了，退出 ，并按照已授权来处理
							copyright = false;	//不显示版权
							return;
						}
						
						if(hr.getCode() == 200){
							//正常，响应 200
							JSONObject json = JSONObject.fromObject(hr.getContent().trim());
							if(json.get("result") != null){
								String result = json.getString("result");
								if(result.equals("1")){
									//授权
									copyright = false;	//不显示版权
								}else{
									//非授权
									copyright = true;	//显示版权
								}
							}else{
								//异常
								//判断是否是第一次运行，如果是软件刚开启时，出现联网异常，那么就认为是已授权的好了
								if(gainNumber == 0){
									copyright = false;	//不显示版权
								}
								
								//如果不是第一次运行了，那就还是按照上次所取到的状态来就好
								gainNumber++;
							}
							
						}else{
							//非正常，响应码不是200，那么就忽略好了,并且以已经授权来处理
							copyright = false;	//不显示版权
						}
						
						//延迟。没间隔一段时间就会请求验证授权是否有效
						try {
							Thread.sleep(sleeptime);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			});
			
			thread.start();//启动
		}
	}
	

	/**
     * 获取当前系统CPU序列，可区分linux系统和windows系统
     */
	private static String getCpuId() throws Exception {
        String cpuId;
        // 获取当前操作系统名称
        String os = System.getProperty("os.name");
        os = os.toUpperCase();
        //System.out.println(os);

        // linux系统用Runtime.getRuntime().exec()执行 dmidecode -t processor 查询cpu序列
        // windows系统用 wmic cpu get ProcessorId 查看cpu序列
        if ("LINUX".equals(os)) {
            cpuId = getLinuxCpuId("dmidecode -t processor | grep 'ID'", "ID", ":");
        } else {
            cpuId = getWindowsCpuId();
        }
        return cpuId.toUpperCase().replace(" ", "");
    }

    /**
     * 获取linux系统CPU序列
     */
    private static String getLinuxCpuId(String cmd, String record, String symbol) throws Exception {
        String execResult = executeLinuxCmd(cmd);
        String[] infos = execResult.split("\n");
        for (String info : infos) {
            info = info.trim();
            if (info.indexOf(record) != -1) {
                info.replace(" ", "");
                String[] sn = info.split(symbol);
                return sn[1];
            }
        }
        return null;
    }

    private static String executeLinuxCmd(String cmd) throws Exception {
        Runtime run = Runtime.getRuntime();
        Process process;
        process = run.exec(cmd);
        InputStream in = process.getInputStream();
        BufferedReader bs = new BufferedReader(new InputStreamReader(in));
        StringBuffer out = new StringBuffer();
        byte[] b = new byte[8192];
        for (int n; (n = in.read(b)) != -1; ) {
            out.append(new String(b, 0, n));
        }
        in.close();
        process.destroy();
        return out.toString();
    }

    /**
     * 获取windows系统CPU序列
     */
    private static String getWindowsCpuId() throws Exception {
        Process process = Runtime.getRuntime().exec(
                new String[]{"wmic", "cpu", "get", "ProcessorId"});
        process.getOutputStream().close();
        Scanner sc = new Scanner(process.getInputStream());
        sc.next();
        String serial = sc.next();
        return serial;
    }
	
	/**
	 * 启动鉴权
	 */
    public Authorization() {
    	auth();
	}
    
	public static void main(String[] args) {
		auth();
	}
	
	
}
